package com.acme.bankapp.domain.bank;

import com.acme.bankapp.account.AccountClosedException;
import com.acme.bankapp.account.AccountState;
import com.acme.bankapp.account.AccountType;
import com.acme.bankapp.account.NotEnoughFundsException;
import com.acme.bankapp.account.OverDraftLimitExceededException;

/**
 * @author Andrey Alekov
 * Bank account interface.
 */
public interface Account {
	/**
	 * Set account state.
	 * @param state to set from state enum
	 */
	public void setState(AccountState state);
	
	/**
	 * Get account state.
	 * @return AccountState from enum
	 */
	public AccountState getState();
	
	/**
	 * This account is opened?
	 * @return boolean result of check
	 */
	public boolean isOpened();
	
	/**
	 * Set account type.
	 * @param type to set
	 * @throws UnsupportedOperationException when account type can't be changed.
	 */
	public void setAccountType(AccountType type) throws UnsupportedOperationException;
	
	/**
	 * Get account type.
	 * @return AccountType of this account
	 */
	public AccountType getAccountType();

	/**
	 * Return account identification number.
	 * @return long actual account balance.
	 */
	public long getAccountId();

	/**
	 * Set account identification number.
	 * @param accountId new actual account identifier.
	 */
	public void setAccountId(long accountId);

	/**
	 * Return actual account balance.
	 * @return double actual account balance.
	 */
	public double getBalance();
	
	/**
	 * Set new account balance.
	 */
	public void setBalance(final double amount);
	
	/**
	 * Return integer value of account balance.
	 * @return long integer value of account balance.
	 */
	public long getDecimalValue();
	
	/**
	 * Return integer value of account balance.
	 * @return Account which are overdraft
	 * @throws UnsupportedOperationException when account not include overdraft
	 */
	public Account getOverdraftAccount() throws UnsupportedOperationException;
	
	/**
	 * Deposit account to amount
	 * @param amount
	 * @return True if operation successful, else return False.
	 * @throws AccountClosedException when account state is closed.
	 */
	public void deposit(double amount) throws IllegalArgumentException, AccountClosedException;
	
	/**
	 * Method check type overdraft account
	 * @return True if account with overdraft
	 */
	public boolean hasOverdraft();

	/** 
	 * Withdraw account to amount.
	 * @param amount to withdraw
	 * @return True if operation successful, else return False.
	 * @throws AccountClosedException when account state is closed.
	 */
	public void withdraw(double amount) throws OverDraftLimitExceededException, 
	NotEnoughFundsException, AccountClosedException;
	
	/**
	 * Return maximum amount to withdraw
	 * @return double amount to withdraw
	 */
	public double maximumAmountToWithdraw();

	/**
	 * Public toString class method.
	 * @return formated class view
	 */
	public String toString();
}